package com.zx.idc.backend.gui.api.management.infosecurity.violationwebsite.filter.service.impl;

import com.alibaba.fastjson.JSON;
import com.zx.idc.backend.gui.api.commom.entity.CommandModel;
import com.zx.idc.backend.gui.api.commom.entity.factory.CommandAckFactory;
import com.zx.idc.backend.gui.api.commom.template.IdcCommandTransferTemplate;
import com.zx.idc.backend.gui.api.commom.utils.ExternalHelper;
import com.zx.idc.backend.gui.api.management.infosecurity.violationwebsite.filter.service.FilterCommandService;
import com.zx.idc.backend.gui.scheduler.ins.filtermonitorlog.service.FilterInstructionJobService;
import com.zx.idc.common.attributes.SchemaFileNameEnum;
import com.zx.idc.common.attributes.SystemAttributes;
import com.zx.idc.common.constants.InsCacheStatus;
import com.zx.idc.common.lang.StringUtil;
import com.zx.idc.ds.common.constant.ReportStatusConstant;
import com.zx.idc.ds.ins.entity.InsAdminControl;
import com.zx.idc.ds.ins.entity.InsFilter;
import com.zx.idc.ds.ins.entity.InsFilterArchive;
import com.zx.idc.ds.ins.entity.InsFilterRule;
import com.zx.idc.ds.ins.service.IInsAdminControlService;
import com.zx.idc.ds.ins.service.IInsFilterArchiveService;
import com.zx.idc.ds.ins.service.IInsFilterRuleService;
import com.zx.idc.ds.ins.service.IInsFilterService;
import com.zx.idc.ds.sys.service.ISysGlobalStatusService;
import com.zx.idc.xml.entity.command.Command;
import com.zx.idc.xml.entity.command.action.Action;
import com.zx.idc.xml.entity.command.privilege.Privilege;
import com.zx.idc.xml.entity.command.rule.Rule;
import com.zx.idc.xml.entity.command.time.Time;
import com.zx.idc.xml.entity.idccommandack.IdcCommandAck;
import com.zx.idc.xml.utils.JaxbUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

import static com.zx.idc.common.constants.IdcCommandAckTypeConstants.ILLEGAL_INFORMATION_FILTER_INSTRUCTION;


/**
 * Created by hasee on 2019/2/19.
 * 违法信息安全管理指令内容
 */
@Service("filterCommandServiceImpl")
@Transactional(rollbackFor = Exception.class)
public class FilterCommandServiceImpl implements FilterCommandService {

    private static final Logger LOG = LoggerFactory.getLogger(FilterCommandServiceImpl.class);

    private static final Integer TYPE_KEYWORD = 3;

    @Autowired
    private IInsFilterService iInsFilterService;
    @Autowired
    private IInsFilterArchiveService insFilterArchiveService;

    @Autowired
    private IInsFilterRuleService iInsFilterRuleService;

    @Autowired
    private IdcCommandTransferTemplate idcCommandTransferTemplate;

    @Autowired
    private FilterInstructionJobService filterInstructionJobService;

    @Autowired
    private ISysGlobalStatusService iSysGlobalStatusService;

    @Autowired
    private IInsAdminControlService iInsAdminControlService;

    @Override
    public void command(Command command, CommandModel commandModel) {

        LOG.debug("Illegal information security management instruction content start!");
        //调用过滤服务
        IdcCommandAck idcCommandAck;
        try {
            String commandId = String.valueOf(command.getCommandId());
            //记录管控指令
            InsAdminControl insAdminControl = new InsAdminControl()
                .setInsType(SystemAttributes.INS_TYPE_ILLEGAL_INFORMATION_SECURITY)
                .setIdcId(commandModel.getIdcId())
                .setCreateTime(command.getTimeStamp())
                .setCommandId(String.valueOf(command.getCommandId()))
                .setReportStatus(ReportStatusConstant.NOT_REPORTED)
                .setInsContents(JSON.toJSONString(command));
            iInsAdminControlService.insert(insAdminControl);
            LOG.debug("过滤指令服务处理执行,指令ID:{}", command.getCommandId());
            //存储命令
            if (InsFilter.OPERATION_TYPE_ADD.equals(command.getOperationType())) {
                LOG.debug("存储命令...");
                insertCommand(command);
            } else {
                LOG.debug("更新指令类型为删除");
                InsFilter insFilter = new InsFilter();
                insFilter.setId(commandId);
                insFilter.setOperationType(InsFilter.OPERATION_TYPE_DELETE);
                iInsFilterService.updateById(insFilter);

                //删除存档指令
                insFilterArchiveService.deleteById(commandId);
            }

            //获取所有的机房,批量修改指令添加清除缓存状态
            LOG.debug("获取所有的机房,批量修改指令添加清除缓存状态");
            iSysGlobalStatusService.updateInsStatusByHouseIds(
                command.getRange().getHouseId(),
                InsCacheStatus.ClEAN_CACHE_NEED
            );

            //调用拦截器
            LOG.debug("添加定时任务调用拦截器");
            filterInstructionJobService.generateScheduler(commandId);

            //指令数据实体
            idcCommandAck = CommandAckFactory.ackSuccess(
                ILLEGAL_INFORMATION_FILTER_INSTRUCTION,
                commandModel,
                commandAck ->
                    commandAck.setCommandId(command.getCommandId())
            );
            //调用回调接口
            LOG.debug("调用管局回调接口...");
            IdcCommandAck finalIdcCommandAck = idcCommandAck;
            ExternalHelper.getExternalWebServiceEnable(() -> {
                LOG.debug("Illegal information security management instruction content callback Administration Interface start!");
                idcCommandTransferTemplate.transferTemplate(commandModel, finalIdcCommandAck, SchemaFileNameEnum.INFO_SECURITY_MANAGEMENT);
                LOG.debug("Illegal information security management instruction content callback Administration Interface done!");
            });
        } catch (Exception e) {
            LOG.error("过滤指令出错 指令ID为:" + command.getCommandId(), e);

            //指令数据实体
            idcCommandAck = CommandAckFactory.ackFail(
                ILLEGAL_INFORMATION_FILTER_INSTRUCTION,
                commandModel,
                "网络错误，请销后重试!",
                commandAck ->
                    commandAck.setCommandId(command.getCommandId())
            );

            //调用回调接口
            LOG.debug("调用管局回调接口...");
            IdcCommandAck finalIdcCommandAck1 = idcCommandAck;
            ExternalHelper.getExternalWebServiceEnable(() -> idcCommandTransferTemplate.transferTemplate(commandModel, finalIdcCommandAck1, SchemaFileNameEnum.INFO_SECURITY_MANAGEMENT));
            throw new RuntimeException(e);
        }
        LOG.debug("Illegal information security management instruction content done!");

    }

    private void insertCommand(Command command) {
        InsFilter insFilter = new InsFilter();
        //过滤信息
        if (ObjectUtils.allNotNull(command.getRange())) {
            List<Long> houseId = command.getRange().getHouseId();
            String s = StringUtil.spliceStringNo(houseId);
            insFilter.setHouseId(s)
                .setIdcId(command.getRange().getIdcId());
        }
        Action action = command.getAction();
        Time time = command.getTime();
        Privilege privilege = command.getPrivilege();
        insFilter.setReason(action.getReason())
            .setLog(action.getLog())
            .setReport(action.getReport())
            .setEffectTime(time.getEffectTime())
            .setExpiredTime(time.getExpiredTime())
            .setOwner(privilege.getOwner())
            .setVisible(privilege.getVisible())
            .setTimeStamp(command.getTimeStamp())
            .setRawPacket(JaxbUtils.beanToXml(command))
            .setOperationType(command.getOperationType())
            .setLevel(command.getLevel())
            .setInsSource(InsFilter.INS_SOURCE_SMMS)
            .setId(String.valueOf(command.getCommandId()));
        insFilter.setReportStatus(ReportStatusConstant.NOT_REPORTED);
        iInsFilterService.insert(insFilter);

        //保存存档，方便后续上报日志的时候查询
        InsFilterArchive insFilterArchive = new InsFilterArchive();
        BeanUtils.copyProperties(insFilter, insFilterArchive);
        insFilterArchiveService.insert(insFilterArchive);

        //过滤规则
        List<Rule> rules = command.getRule();
        if (rules != null) {
            iInsFilterRuleService.insertBatch(
                rules.stream().map((rule) -> {
                    InsFilterRule insFilterRule = new InsFilterRule();
                    insFilterRule.setInsId(insFilter.getId());
                    insFilterRule.setKeywordRange(StringUtil.spliceStringNo(rule.getKeywordRange()));
                    insFilterRule.setSubtype(rule.getSubtype());
                    insFilterRule.setValueStart(rule.getValueStart());
                    insFilterRule.setValueEnd(rule.getValueEnd());
                    return insFilterRule;
                }).collect(Collectors.toList())
            );
        }

    }
}
